/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Mainframe.java
 *
 * Created on 09-août-2010, 16:01:15
 */
package com.google.code.p.narcissus.ui;

import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

import org.apache.commons.io.comparator.NameFileComparator;
import org.apache.log4j.Logger;

import com.google.code.p.narcissus.core.NarcissusException;
import com.google.code.p.narcissus.core.ScreenShooter;
import com.google.code.p.narcissus.core.model.ReferenceMetaData;
import com.google.code.p.narcissus.core.reference.ReferenceMetaDataMapper;
import com.google.code.p.narcissus.ui.components.ComparisonTreeCellRenderer;
import com.google.code.p.narcissus.ui.components.EditionMode;
import com.google.code.p.narcissus.ui.components.LogFrame;
import com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton;
import com.google.code.p.narcissus.ui.components.utils.ComparisonMode;
import com.google.code.p.narcissus.ui.components.utils.FileHandlingUtility;
import com.google.code.p.narcissus.ui.listeners.FolderListener;
import com.google.code.p.narcissus.ui.listeners.ReferenceCommentsListener;
import com.google.code.p.narcissus.ui.listeners.ReferencePaneMouseEventListener;
import com.google.code.p.narcissus.ui.preferences.NarcissusUIPreferences;
import com.google.code.p.narcissus.ui.preferences.ReferenceComments;

/**
 * @author jadoj
 */
public class Mainframe extends javax.swing.JFrame {

	public static final String REFERENCES = "References";

	public static final String TEST_RUNS = "Test runs";

	private static final String ROOT_FOLDER_LABEL = "Root folder: ";

	private static final Logger LOGGER = Logger.getLogger(Mainframe.class.getName());

	private NarcissusUIPreferences preferences = NarcissusUIPreferences.getInstance();

	private List<FolderListener> rootFolderListeners = new ArrayList<FolderListener>();

	private List<ReferenceCommentsListener> referenceCommentsListeners = new ArrayList<ReferenceCommentsListener>();
	
	private Mode currentMode;

	//this should be putted in a properties file and updated in preferences.
	private static final String DEFAULT_ROOT_FOLDER = "K:/Theseos_Team/Projects/Payments/3 - Output/4 - Testing/IT Testing/19 Selenium Regression Tests/Narcissus";

	/** Creates new form Mainframe */
	public Mainframe() {
		try {
			UIManager.setLookAndFeel("com.petersoft.white.PetersoftWhiteLookAndFeel");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		LOGGER.info("Narcissus UI Started!");
		initComponents();
		addSpecificListeners();

		comparisonModeTree.setCellRenderer(new ComparisonTreeCellRenderer());

		if (preferences.getReferenceCommentsFile() != null) {
			ReferenceComments.setReferenceCommentsFile(preferences.getReferenceCommentsFile());
		}

		if (preferences.getRootFolder() != null) {
			rootFolderUpdated();
		} else {
			preferences.setRootFolder(DEFAULT_ROOT_FOLDER);
			preferences.save();
			rootFolderUpdated();
		}
	}

	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form
	 * Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {
		java.awt.GridBagConstraints gridBagConstraints;

		aboutDialog = new javax.swing.JDialog();
		jPanel6 = new javax.swing.JPanel();
		jLabel5 = new javax.swing.JLabel();
		jLabel4 = new javax.swing.JLabel();
		jLabel6 = new javax.swing.JLabel();
		fileChooser = new javax.swing.JFileChooser();
		applicationInfoPanel = new javax.swing.JPanel();
		rootFolderLabel = new javax.swing.JLabel();
		jTabbedPane1 = new javax.swing.JTabbedPane();
		referenceModeSplitPane = new javax.swing.JSplitPane();
		referenceModeScrollPane = new javax.swing.JScrollPane();
		referenceModeTree = new javax.swing.JTree();
		ReferenceModePanel = new javax.swing.JPanel();
		optionsToolBar = new javax.swing.JToolBar();
		exclusionZoneAdd = new javax.swing.JButton();
		exclusionZoneRemove = new javax.swing.JButton();
		jPanel5 = new javax.swing.JPanel();
		jLabel3 = new javax.swing.JLabel();
		jScrollPane1 = new javax.swing.JScrollPane();
		referenceComment = new javax.swing.JTextArea();
		jScrollPane4 = new javax.swing.JScrollPane();
		referenceImagePanel = new com.google.code.p.narcissus.ui.components.ReferenceImagePanel();
		comparisonModeSplitPane = new javax.swing.JSplitPane();
		comparisonModeScrollPane = new javax.swing.JScrollPane();
		comparisonModeTree = new javax.swing.JTree();
		comparisonSplitPane = new javax.swing.JSplitPane();
		jPanel1 = new javax.swing.JPanel();
		jPanel4 = new javax.swing.JPanel();
		jLabel2 = new javax.swing.JLabel();
		jToolBar1 = new javax.swing.JToolBar();
		diffDrawnBtn = new com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton();
		diffOnlyBtn = new com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton();
		flipBtn = new com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton();
		xorBtn = new com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton();
		jScrollPane2 = new javax.swing.JScrollPane();
		comparisonScreenshotPanel = new com.google.code.p.narcissus.ui.components.PictureComparisonPanel();
		jPanel2 = new javax.swing.JPanel();
		jPanel3 = new javax.swing.JPanel();
		jLabel1 = new javax.swing.JLabel();
		jToolBar2 = new javax.swing.JToolBar();
		jScrollPane3 = new javax.swing.JScrollPane();
		comparisonReferencePanel = new com.google.code.p.narcissus.ui.components.ReferenceImagePanel();
		menuBar = new javax.swing.JMenuBar();
		fileMenu = new javax.swing.JMenu();
		openMenuItem = new javax.swing.JMenuItem();
		openReferenceCommentsMenuItem = new javax.swing.JMenuItem();
		saveExclusionZonesMenuItem = new javax.swing.JMenuItem();
		exportExclusionZonesMenuItem = new javax.swing.JMenuItem();
		showLogsMenuItem = new javax.swing.JMenuItem();
		exitMenuItem = new javax.swing.JMenuItem();
		helpMenu = new javax.swing.JMenu();
		aboutMenuItem = new javax.swing.JMenuItem();

		aboutDialog.setTitle("About");
		aboutDialog.setMinimumSize(new java.awt.Dimension(230, 170));
		aboutDialog.setResizable(false);

		jPanel6.setMinimumSize(new java.awt.Dimension(230, 150));
		jPanel6.setPreferredSize(new java.awt.Dimension(230, 150));
		jPanel6.setLayout(new java.awt.GridLayout(3, 1));

		jLabel5.setFont(new java.awt.Font("Lucida Sans Typewriter", 3, 24));
		jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
		jLabel5.setText("Narcissus UI");
		jLabel5.setPreferredSize(new java.awt.Dimension(264, 50));
		jPanel6.add(jLabel5);

		jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
		jLabel4.setText("JADOULLE Jerome - Theseos Team");
		jPanel6.add(jLabel4);

		jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
		jLabel6.setText("National Pension Office - 2010");
		jPanel6.add(jLabel6);

		javax.swing.GroupLayout aboutDialogLayout = new javax.swing.GroupLayout(aboutDialog.getContentPane());
		aboutDialog.getContentPane().setLayout(aboutDialogLayout);
		aboutDialogLayout.setHorizontalGroup(aboutDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jPanel6,
		    javax.swing.GroupLayout.PREFERRED_SIZE, 230, javax.swing.GroupLayout.PREFERRED_SIZE));
		aboutDialogLayout.setVerticalGroup(aboutDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jPanel6,
		    javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE));

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		setTitle("Narcissus");
		setMinimumSize(new java.awt.Dimension(1280, 768));
		setName("mainFrame"); // NOI18N
		getContentPane().setLayout(new java.awt.GridBagLayout());

		applicationInfoPanel.setPreferredSize(new java.awt.Dimension(Integer.MAX_VALUE, 30));
		applicationInfoPanel.setLayout(new java.awt.BorderLayout());

		rootFolderLabel.setText("Root folder: ");
		applicationInfoPanel.add(rootFolderLabel, java.awt.BorderLayout.CENTER);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
		getContentPane().add(applicationInfoPanel, gridBagConstraints);

		jTabbedPane1.setMaximumSize(null);
		jTabbedPane1.addChangeListener(new javax.swing.event.ChangeListener() {
			public void stateChanged(javax.swing.event.ChangeEvent evt) {
				jTabbedPane1StateChanged(evt);
			}
		});

		referenceModeSplitPane.setDividerSize(4);
		referenceModeSplitPane.setResizeWeight(0.2);

		referenceModeScrollPane.setAutoscrolls(true);
		referenceModeScrollPane.setMaximumSize(new java.awt.Dimension(400, 2000));
		referenceModeScrollPane.setMinimumSize(null);
		referenceModeScrollPane.setPreferredSize(new java.awt.Dimension(250, 400));

		referenceModeTree.setMaximumSize(null);
		referenceModeTree.setMinimumSize(new java.awt.Dimension(100, 100));
		referenceModeTree.setPreferredSize(new java.awt.Dimension(210, 210));
		referenceModeTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
			public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
				referenceModeTreeValueChanged(evt);
			}
		});
		referenceModeScrollPane.setViewportView(referenceModeTree);

		referenceModeSplitPane.setLeftComponent(referenceModeScrollPane);

		ReferenceModePanel.setLayout(new java.awt.GridBagLayout());

		optionsToolBar.setRollover(true);

		exclusionZoneAdd.setText("Add exclusion zone");
		exclusionZoneAdd.setFocusable(false);
		exclusionZoneAdd.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		exclusionZoneAdd.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		exclusionZoneAdd.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				exclusionZoneAddActionPerformed(evt);
			}
		});
		optionsToolBar.add(exclusionZoneAdd);

		exclusionZoneRemove.setText("Remove exclusion zone");
		exclusionZoneRemove.setFocusable(false);
		exclusionZoneRemove.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		exclusionZoneRemove.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		exclusionZoneRemove.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				exclusionZoneRemoveActionPerformed(evt);
			}
		});
		optionsToolBar.add(exclusionZoneRemove);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
		ReferenceModePanel.add(optionsToolBar, gridBagConstraints);

		jPanel5.setMaximumSize(new java.awt.Dimension(50, 50));
		jPanel5.setMinimumSize(new java.awt.Dimension(50, 50));
		jPanel5.setPreferredSize(new java.awt.Dimension(50, 50));
		jPanel5.setLayout(new java.awt.GridBagLayout());

		jLabel3.setText("Reference comment: ");
		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
		jPanel5.add(jLabel3, gridBagConstraints);

		jScrollPane1.setMaximumSize(null);
		jScrollPane1.setMinimumSize(null);

		referenceComment.setColumns(1);
		referenceComment.setEditable(false);
		referenceComment.setRows(1);
		referenceComment.setMaximumSize(null);
		referenceComment.setMinimumSize(null);
		jScrollPane1.setViewportView(referenceComment);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 1;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
		jPanel5.add(jScrollPane1, gridBagConstraints);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 2;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
		ReferenceModePanel.add(jPanel5, gridBagConstraints);

		javax.swing.GroupLayout referenceImagePanelLayout = new javax.swing.GroupLayout(referenceImagePanel);
		referenceImagePanel.setLayout(referenceImagePanelLayout);
		referenceImagePanelLayout.setHorizontalGroup(referenceImagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 898, Short.MAX_VALUE));
		referenceImagePanelLayout.setVerticalGroup(referenceImagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 478, Short.MAX_VALUE));

		jScrollPane4.setViewportView(referenceImagePanel);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		ReferenceModePanel.add(jScrollPane4, gridBagConstraints);

		referenceModeSplitPane.setRightComponent(ReferenceModePanel);

		jTabbedPane1.addTab("Reference mode", referenceModeSplitPane);

		comparisonModeSplitPane.setDividerSize(4);
		comparisonModeSplitPane.setResizeWeight(0.2);
		comparisonModeSplitPane.setMaximumSize(null);

		comparisonModeScrollPane.setMaximumSize(new java.awt.Dimension(400, 2000));
		comparisonModeScrollPane.setMinimumSize(null);
		comparisonModeScrollPane.setPreferredSize(new java.awt.Dimension(250, 400));

		comparisonModeTree.setMaximumSize(null);
		comparisonModeTree.setMinimumSize(null);
		comparisonModeTree.setPreferredSize(null);
		comparisonModeTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
			public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
				comparisonModeTreeValueChanged(evt);
			}
		});
		comparisonModeScrollPane.setViewportView(comparisonModeTree);

		comparisonModeSplitPane.setLeftComponent(comparisonModeScrollPane);

		comparisonSplitPane.setDividerSize(4);
		comparisonSplitPane.setResizeWeight(0.5);
		comparisonSplitPane.setMaximumSize(null);

		jPanel1.setLayout(new java.awt.GridBagLayout());

		jPanel4.setMaximumSize(new java.awt.Dimension(20, 20));
		jPanel4.setMinimumSize(new java.awt.Dimension(20, 20));
		jPanel4.setPreferredSize(new java.awt.Dimension(20, 20));
		jPanel4.setLayout(new javax.swing.BoxLayout(jPanel4, javax.swing.BoxLayout.LINE_AXIS));

		jLabel2.setText("Screenshot:");
		jPanel4.add(jLabel2);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		jPanel1.add(jPanel4, gridBagConstraints);

		jToolBar1.setFloatable(false);
		jToolBar1.setRollover(true);
		jToolBar1.setMaximumSize(new java.awt.Dimension(13, 26));
		jToolBar1.setMinimumSize(new java.awt.Dimension(13, 26));
		jToolBar1.setPreferredSize(new java.awt.Dimension(13, 26));

		diffDrawnBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/google/code/p/narcissus/ui/icons/difference.png"))); // NOI18N
		diffDrawnBtn.setSelected(true);
		diffDrawnBtn.setToolTipText("Differences zone drawn over screenshot");
		diffDrawnBtn.setFocusable(false);
		diffDrawnBtn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		diffDrawnBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		jToolBar1.add(diffDrawnBtn);

		diffOnlyBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/google/code/p/narcissus/ui/icons/differencesOnly.png"))); // NOI18N
		diffOnlyBtn.setToolTipText("Differences zones only are displayed");
		diffOnlyBtn.setFocusable(false);
		diffOnlyBtn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		diffOnlyBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		jToolBar1.add(diffOnlyBtn);

		flipBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/google/code/p/narcissus/ui/icons/flip.png"))); // NOI18N
		flipBtn.setToolTipText("Flipping from reference to screenshot");
		flipBtn.setFocusable(false);
		flipBtn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		flipBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		jToolBar1.add(flipBtn);

		xorBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/google/code/p/narcissus/ui/icons/xor.png"))); // NOI18N
		xorBtn.setToolTipText("Only different pixels are displayed");
		xorBtn.setFocusable(false);
		xorBtn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
		xorBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
		jToolBar1.add(xorBtn);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		jPanel1.add(jToolBar1, gridBagConstraints);

		jScrollPane2.setMaximumSize(null);
		jScrollPane2.setMinimumSize(null);

		comparisonScreenshotPanel.setMaximumSize(null);
		comparisonScreenshotPanel.setPictureComparison(null);

		javax.swing.GroupLayout comparisonScreenshotPanelLayout = new javax.swing.GroupLayout(comparisonScreenshotPanel);
		comparisonScreenshotPanel.setLayout(comparisonScreenshotPanelLayout);
		comparisonScreenshotPanelLayout.setHorizontalGroup(comparisonScreenshotPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 500,
		    Short.MAX_VALUE));
		comparisonScreenshotPanelLayout
		    .setVerticalGroup(comparisonScreenshotPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 500, Short.MAX_VALUE));

		jScrollPane2.setViewportView(comparisonScreenshotPanel);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 2;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		jPanel1.add(jScrollPane2, gridBagConstraints);

		comparisonSplitPane.setLeftComponent(jPanel1);

		jPanel2.setLayout(new java.awt.GridBagLayout());

		jPanel3.setMaximumSize(new java.awt.Dimension(20, 20));
		jPanel3.setMinimumSize(new java.awt.Dimension(20, 20));
		jPanel3.setPreferredSize(new java.awt.Dimension(20, 20));
		jPanel3.setLayout(new javax.swing.BoxLayout(jPanel3, javax.swing.BoxLayout.LINE_AXIS));

		jLabel1.setText("Reference:");
		jPanel3.add(jLabel1);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		jPanel2.add(jPanel3, gridBagConstraints);

		jToolBar2.setFloatable(false);
		jToolBar2.setRollover(true);
		jToolBar2.setMaximumSize(new java.awt.Dimension(13, 26));
		jToolBar2.setMinimumSize(new java.awt.Dimension(13, 26));
		jToolBar2.setPreferredSize(new java.awt.Dimension(13, 26));
		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
		jPanel2.add(jToolBar2, gridBagConstraints);

		comparisonReferencePanel.setMaximumSize(null);

		javax.swing.GroupLayout comparisonReferencePanelLayout = new javax.swing.GroupLayout(comparisonReferencePanel);
		comparisonReferencePanel.setLayout(comparisonReferencePanelLayout);
		comparisonReferencePanelLayout
		    .setHorizontalGroup(comparisonReferencePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 602, Short.MAX_VALUE));
		comparisonReferencePanelLayout.setVerticalGroup(comparisonReferencePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 501, Short.MAX_VALUE));

		jScrollPane3.setViewportView(comparisonReferencePanel);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 2;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		jPanel2.add(jScrollPane3, gridBagConstraints);

		comparisonSplitPane.setRightComponent(jPanel2);

		comparisonModeSplitPane.setRightComponent(comparisonSplitPane);

		jTabbedPane1.addTab("Comparison mode", comparisonModeSplitPane);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		getContentPane().add(jTabbedPane1, gridBagConstraints);

		fileMenu.setText("File");

		openMenuItem.setText("Open test root folder");
		openMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				openMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(openMenuItem);

		openReferenceCommentsMenuItem.setText("Open reference comments");
		openReferenceCommentsMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				openReferenceCommentsMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(openReferenceCommentsMenuItem);
		
		saveExclusionZonesMenuItem.setText("Save exclusion Zones");
		saveExclusionZonesMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				saveExclusionZonesMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(saveExclusionZonesMenuItem);
		
		
		exportExclusionZonesMenuItem.setText("Export exclusion Zones...");
		exportExclusionZonesMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				saveExclusionZonesMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(exportExclusionZonesMenuItem);
		
		showLogsMenuItem.setText("Show logs");
		showLogsMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				showLogsMenuItemActionPerformed(evt);
			}
		});
		
		
		
		fileMenu.add(showLogsMenuItem);

		exitMenuItem.setText("Exit");
		exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				exitMenuItemActionPerformed(evt);
			}
		});
		fileMenu.add(exitMenuItem);

		menuBar.add(fileMenu);

		helpMenu.setText("Help");

		aboutMenuItem.setText("About");
		aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				aboutMenuItemActionPerformed(evt);
			}
		});
		helpMenu.add(aboutMenuItem);

		menuBar.add(helpMenu);

		setJMenuBar(menuBar);

		pack();
	}// </editor-fold>//GEN-END:initComponents

	private void showLogsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showLogsMenuItemActionPerformed
		// TODO add your handling code here:
		showLogFrame();
	}//GEN-LAST:event_showLogsMenuItemActionPerformed

	private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_exitMenuItemActionPerformed
		System.exit(0);
	}// GEN-LAST:event_exitMenuItemActionPerformed

	private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_openMenuItemActionPerformed
		// Select root folder for screenshots
		fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		if (preferences.getRootFolder() != null) {
			fileChooser.setCurrentDirectory(new File(preferences.getRootFolder()));
		}
		int returnVal = fileChooser.showOpenDialog(this);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File rootFolder = fileChooser.getSelectedFile();

			if (!rootFolder.getAbsolutePath().equals(preferences.getRootFolder())) {
				preferences.setRootFolder(rootFolder.getAbsolutePath());
				preferences.save();
			}

			rootFolderUpdated();
		}
	}// GEN-LAST:event_openMenuItemActionPerformed

	private void exclusionZoneAddActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_exclusionZoneAddActionPerformed
		//switching to Edition Mode.
		if(EditionMode.ReadOnly.equals(referenceImagePanel.getCurrentEditionMode())){
			referenceImagePanel.setCurrentEditionMode(EditionMode.inEdtion);
		}else{
			referenceImagePanel.setCurrentEditionMode(EditionMode.ReadOnly);
		}
	}// GEN-LAST:event_exclusionZoneAddActionPerformed
	
	private void exclusionZoneRemoveActionPerformed(ActionEvent evt) {
		// TODO Auto-generated method stub
		referenceImagePanel.setCurrentEditionMode(EditionMode.inDeletion);
	}

	private void referenceModeTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {// GEN-FIRST:event_referenceModeTreeValueChanged
		final Object lastSelectedPathComponent = referenceModeTree.getLastSelectedPathComponent();
		//Add Promp for referenceMetaData xml Save;
		if (lastSelectedPathComponent != null) {
			Object selectedNode = ((DefaultMutableTreeNode) lastSelectedPathComponent).getUserObject();
			if (selectedNode instanceof TestReference) {
				try {
					TestReference selectedTestReference = (TestReference) selectedNode;
					referenceImagePanel.setImage(selectedTestReference.getReferenceFile());
					referenceImagePanel.setMetaData(selectedTestReference.getMetaData());
					String comment;
					if (selectedTestReference.metaDataExists()) {
						comment = selectedTestReference.getMetaData().getComment();
					} else {
						comment = "";
					}
					referenceComment.setText(comment);
				} catch (IOException referenceFileNotLoadableEx) {
					LOGGER.error(referenceFileNotLoadableEx);
					JOptionPane.showMessageDialog(this, this.getClass().getName() + ".referenceFileNotLoadableEx");
				}
			}
		}
	}// GEN-LAST:event_referenceModeTreeValueChanged

	private void comparisonModeTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {// GEN-FIRST:event_comparisonModeTreeValueChanged
		final Object lastSelectedPathComponent = comparisonModeTree.getLastSelectedPathComponent();
		if (lastSelectedPathComponent != null) {
			Object selectedNode = ((DefaultMutableTreeNode) lastSelectedPathComponent).getUserObject();
			if (selectedNode instanceof TestRun) {
				try {
					TestRun selectedTestRun = (TestRun) selectedNode;
					comparisonReferencePanel.setImage(selectedTestRun.getReferenceFile());
					comparisonReferencePanel.setMetaData(selectedTestRun.getMetaData());

					comparisonScreenshotPanel.setImage(selectedTestRun.getComparisonScreenshot());
					comparisonScreenshotPanel.setPictureComparison(selectedTestRun.getComparison());
					comparisonScreenshotPanel.setReference(selectedTestRun.getReferenceFile());
					comparisonScreenshotPanel.setReferenceMetaData(selectedTestRun.getMetaData());
				} catch (IOException fileNotReadableEx) {
					LOGGER.error(fileNotReadableEx);
					JOptionPane.showMessageDialog(this, this.getClass().getName() + ".fileNotLoadableEx");
				}
			}
		}
	}// GEN-LAST:event_comparisonModeTreeValueChanged

	private void jTabbedPane1StateChanged(javax.swing.event.ChangeEvent evt) {// GEN-FIRST:event_jTabbedPane1StateChanged
		// TODO add your handling code here:
		JTabbedPane tabbedPane = (JTabbedPane) evt.getSource();
		if (tabbedPane.getSelectedIndex() != 1) {
			comparisonScreenshotPanel.hidden();
		} else {
			comparisonScreenshotPanel.displayed();
		}
	}// GEN-LAST:event_jTabbedPane1StateChanged
	
	private void saveExclusionZonesMenuItemActionPerformed(java.awt.event.ActionEvent evt){
		ReferenceMetaData metaData = referenceImagePanel.getMetaData();
		TreePath[] selectionPaths = referenceModeTree.getSelectionPaths();
		
		fileChooser.setFileSelectionMode(JFileChooser.SAVE_DIALOG);
		fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {

			@Override
			public boolean accept(File f) {
				return f.isDirectory() || f.getName().toLowerCase().endsWith(".xml");
			}

			@Override
			public String getDescription() {
				return "Reference meta data file";
			}
		});
		int returnVal = fileChooser.showOpenDialog(this);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File referenceCommentsFile = fileChooser.getSelectedFile();
			try {
				ReferenceMetaDataMapper.toXml(metaData, referenceCommentsFile);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NarcissusException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	private void exportExclusionZonesMenuItemActionPerformed(java.awt.event.ActionEvent evt){
		//openPromptWindow
		//Choose Images to reference
		//Export bunch of Exclusion zones in one xml with referenced Images.
	}

	private void openReferenceCommentsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_openReferenceCommentsMenuItemActionPerformed
		// Select reference comments file (used to help testers realize when something is not right)
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {

			@Override
			public boolean accept(File f) {
				return f.isDirectory() || f.getName().toLowerCase().endsWith(".csv");
			}

			@Override
			public String getDescription() {
				return "Reference comments files (.csv)";
			}
		});
		if (preferences.getReferenceCommentsFile() != null) {
			fileChooser.setCurrentDirectory(new File(preferences.getReferenceCommentsFile()).getParentFile());
		}
		int returnVal = fileChooser.showOpenDialog(this);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File referenceCommentsFile = fileChooser.getSelectedFile();

			if (!referenceCommentsFile.getAbsolutePath().equals(preferences.getReferenceCommentsFile())) {
				preferences.setReferenceCommentsFile(referenceCommentsFile.getAbsolutePath());
				preferences.save();
			}

			ReferenceComments.setReferenceCommentsFile(referenceCommentsFile);
			referenceCommentsUpdated();
		}
	}// GEN-LAST:event_openReferenceCommentsMenuItemActionPerformed

	private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_aboutMenuItemActionPerformed
		aboutDialog.setVisible(true);
	}// GEN-LAST:event_aboutMenuItemActionPerformed

	/**
	 * @param args
	 *          the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				new Mainframe().setVisible(true);
			}
		});
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JPanel ReferenceModePanel;
	private javax.swing.JDialog aboutDialog;
	private javax.swing.JMenuItem aboutMenuItem;
	private javax.swing.JPanel applicationInfoPanel;
	private javax.swing.JScrollPane comparisonModeScrollPane;
	private javax.swing.JSplitPane comparisonModeSplitPane;
	private javax.swing.JTree comparisonModeTree;
	private com.google.code.p.narcissus.ui.components.ReferenceImagePanel comparisonReferencePanel;
	private com.google.code.p.narcissus.ui.components.PictureComparisonPanel comparisonScreenshotPanel;
	private javax.swing.JSplitPane comparisonSplitPane;
	private com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton diffDrawnBtn;
	private com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton diffOnlyBtn;
	private javax.swing.JButton exclusionZoneAdd;
	private javax.swing.JButton exclusionZoneRemove;
	private javax.swing.JMenuItem exitMenuItem;
	private javax.swing.JFileChooser fileChooser;
	private javax.swing.JMenu fileMenu;
	private com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton flipBtn;
	private javax.swing.JMenu helpMenu;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JLabel jLabel2;
	private javax.swing.JLabel jLabel3;
	private javax.swing.JLabel jLabel4;
	private javax.swing.JLabel jLabel5;
	private javax.swing.JLabel jLabel6;
	private javax.swing.JPanel jPanel1;
	private javax.swing.JPanel jPanel2;
	private javax.swing.JPanel jPanel3;
	private javax.swing.JPanel jPanel4;
	private javax.swing.JPanel jPanel5;
	private javax.swing.JPanel jPanel6;
	private javax.swing.JScrollPane jScrollPane1;
	private javax.swing.JScrollPane jScrollPane2;
	private javax.swing.JScrollPane jScrollPane3;
	private javax.swing.JScrollPane jScrollPane4;
	private javax.swing.JTabbedPane jTabbedPane1;
	private javax.swing.JToolBar jToolBar1;
	private javax.swing.JToolBar jToolBar2;
	private javax.swing.JMenuBar menuBar;
	private javax.swing.JMenuItem openMenuItem;
	private javax.swing.JMenuItem openReferenceCommentsMenuItem;
	private javax.swing.JMenuItem saveExclusionZonesMenuItem;
	private javax.swing.JMenuItem exportExclusionZonesMenuItem;
	private javax.swing.JToolBar optionsToolBar;
	private javax.swing.JTextArea referenceComment;
	private com.google.code.p.narcissus.ui.components.ReferenceImagePanel referenceImagePanel;
	private javax.swing.JScrollPane referenceModeScrollPane;
	private javax.swing.JSplitPane referenceModeSplitPane;
	private javax.swing.JTree referenceModeTree;
	private javax.swing.JLabel rootFolderLabel;
	private javax.swing.JMenuItem showLogsMenuItem;
	private com.google.code.p.narcissus.ui.components.toolbar.ToggleToolbarButton xorBtn;

	// End of variables declaration//GEN-END:variables

	/**
	 * Builds tree of reference pictures from <code>rootFolder</code>
	 * 
	 * @param rootFolder
	 */
	private void rebuildReferenceTree(File rootFolder) throws NarcissusException {
		File referenceFolder = new File(rootFolder, ScreenShooter.REFERENCES_FOLDER_NAME);
		if (!referenceFolder.exists() || !referenceFolder.isDirectory()) {
			referenceModeTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(REFERENCES)));
		} else {
			referenceModeTree.setModel(new DefaultTreeModel(buildReferenceTreeNode(referenceFolder)));
		}
	}

	/**
	 * Builds tree of reference and screenshots from the <code>rootFolder</code>
	 * 
	 * @param rootFolder
	 */
	private void rebuildComparisonTree(File rootFolder) throws NarcissusException {
		if (!rootFolder.exists() || !rootFolder.isDirectory()) {
			comparisonModeTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(TEST_RUNS)));
		} else {

			DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(TEST_RUNS);

			File[] listFiles = rootFolder.listFiles(new FileFilter() {

				@Override
				public boolean accept(File pathname) {
					return pathname.isDirectory() && !ScreenShooter.REFERENCES_FOLDER_NAME.equals(pathname.getName()) && pathname.getName().endsWith("testRun");
				}
			});
			
			Arrays.sort(listFiles, FileHandlingUtility.createFileNameComparator());
			
			for (File currentFolder : listFiles) {
				rootNode.add(buildTestRunTreeNode(currentFolder));
			}

			comparisonModeTree.setModel(new DefaultTreeModel(rootNode));
		}
	}

	private MutableTreeNode buildReferenceTreeNode(File nodeFolder) {
		final DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode(nodeFolder.getName());
		File[] listFiles = nodeFolder.listFiles(FileHandlingUtility.createDirectoryFilter());
		
		Arrays.sort(listFiles, FileHandlingUtility.createFileNameComparator());
		
		for (File currentFolder : listFiles) {
			currentNode.add(buildReferenceTreeNode(currentFolder));
		}
		
		listFiles = nodeFolder.listFiles(FileHandlingUtility.createExtensionFilter("png"));
		
		Arrays.sort(listFiles, FileHandlingUtility.createFileNameComparator());

		for (File currentTest : listFiles) {
			try {
				// Create the TestReference object here and add to the list
				currentNode.add(new DefaultMutableTreeNode(new TestReference(currentTest)));
			} catch (NarcissusException impossibleToReadReferenceEx) {
				LOGGER.error("Impossible to create reference tree node", impossibleToReadReferenceEx);
			}
		}

		return currentNode;
	}

	private MutableTreeNode buildTestRunTreeNode(File nodeFolder) {
		final DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode(nodeFolder.getName());
		File[] listFiles = nodeFolder.listFiles(FileHandlingUtility.createDirectoryFilter());
		Arrays.sort(listFiles, FileHandlingUtility.createFileNameComparator());
		for (File currentFolder : listFiles) {
			currentNode.add(buildTestRunTreeNode(currentFolder));
		}

		listFiles = nodeFolder.listFiles(FileHandlingUtility.createExtensionFilter("xml"));
		Arrays.sort(listFiles, FileHandlingUtility.createFileNameComparator());
		for (File currentComparisonXML : listFiles) {
			try {
				// Create the TestRun object here and add to the list
				final DefaultMutableTreeNode defaultMutableTreeNode = new DefaultMutableTreeNode(new TestRun(currentComparisonXML, getReferenceScreenshotFromComparisonXML(
				    currentComparisonXML, preferences.getRootFolder())));
				currentNode.add(defaultMutableTreeNode);
			} catch (NarcissusException impossibleToReadComparisonEx) {
				LOGGER.error("Impossible to create test screenshot tree node", impossibleToReadComparisonEx);
			}
		}

		return currentNode;
	}

	private void rootFolderUpdated() {
		for (FolderListener currentListener : rootFolderListeners) {
			currentListener.folderUpdated();
		}
	}

	private void addSpecificListeners() {
		rootFolderListeners.add(new FolderListener() {

			@Override
			public void folderUpdated() {
				final File rootFolder = new File(preferences.getRootFolder());

				try {
					rebuildReferenceTree(rootFolder);
					rebuildComparisonTree(rootFolder);
				} catch (NarcissusException ex) {
					JOptionPane.showMessageDialog(Mainframe.this, "Impossible to reload trees: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);

				}

				rootFolderLabel.setText(ROOT_FOLDER_LABEL + rootFolder.getAbsolutePath());
			}
		});

		referenceCommentsListeners.add(new ReferenceCommentsListener() {

			@Override
			public void referenceCommentsUpdated() {
				// For each reference in the reference tree, check whether it has a comment set for it and, if it is the case, save it.
				DefaultTreeModel referenceModel = (DefaultTreeModel) referenceModeTree.getModel();
				DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) referenceModel.getRoot();
				updateReferenceComment(rootNode);

				// Update the ReferenceComment label;
				final DefaultMutableTreeNode lastSelectedNode = (DefaultMutableTreeNode) referenceModeTree.getLastSelectedPathComponent();
				if (lastSelectedNode != null && lastSelectedNode.isLeaf()) {
					ReferenceMetaData referenceMetaData = ((TestReference) lastSelectedNode.getUserObject()).getMetaData();
					if (referenceMetaData != null) {
						referenceComment.setText(referenceMetaData.getComment());
					}
				}
			}

			private void updateReferenceComment(DefaultMutableTreeNode node) {
				if (node.isLeaf() && node.getUserObject() != null && node.getUserObject() instanceof TestReference) {
					TestReference reference = (TestReference) node.getUserObject();

					// If there is a reference comment for this reference
					String csvComment = getCommentFromCSV(reference.getReferenceFile().getName().substring(0, reference.getReferenceFile().getName().length() - 4));
					if (reference.getMetaData() == null) {
						ReferenceMetaData referenceMetaData = new ReferenceMetaData(null, csvComment);
						referenceMetaData.setCreationDate(new Date(reference.getReferenceFile().lastModified()));
						reference.setMetaData(referenceMetaData);
						try {
							ReferenceMetaDataMapper.toXml(referenceMetaData, ReferenceMetaDataMapper.getMetaDataFile(reference.getReferenceFile()));
						} catch (FileNotFoundException ex) {
							LOGGER.error("Impossible to save reference meta data file for reference: " + reference.getReferenceFile().getName(), ex);
						} catch (NarcissusException ex) {
							LOGGER.error("Impossible to save reference meta data file for reference: " + reference.getReferenceFile().getName(), ex);
						}
					} else {
						// Reference meta data already exists
						// MetaData won't be updated if no csvComment was found relating to the reference at hand.
						if (csvComment != null && !csvComment.equals(reference.getMetaData().getComment())) {
							reference.getMetaData().setComment(csvComment);
							try {
								ReferenceMetaDataMapper.toXml(reference.getMetaData(), ReferenceMetaDataMapper.getMetaDataFile(reference.getReferenceFile()));
							} catch (FileNotFoundException ex) {
								LOGGER.error("Impossible to save reference meta data file for reference: " + reference.getReferenceFile().getName(), ex);
							} catch (NarcissusException ex) {
								LOGGER.error("Impossible to save reference meta data file for reference: " + reference.getReferenceFile().getName(), ex);
							}

						}
					}
				} else {
					// Node is not a leaf.
					for (int childCounter = 0; childCounter < node.getChildCount(); childCounter++) {
						updateReferenceComment((DefaultMutableTreeNode) node.getChildAt(childCounter));
					}
				}
			}
		});

		ActionListener toolbarActionListener = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				ToggleToolbarButton sourceButton = (ToggleToolbarButton) e.getSource();
				if (sourceButton.equals(diffDrawnBtn)) {
					diffDrawnButtonSelected();
				} else if (sourceButton.equals(diffOnlyBtn)) {
					diffOnlyButtonSelected();
				} else if (sourceButton.equals(xorBtn)) {
					xorButtonSelected();
				} else if (sourceButton.equals(flipBtn)) {
					flipButtonSelected();
				}
			}

			private void diffDrawnButtonSelected() {
				diffOnlyBtn.setSelected(false);
				xorBtn.setSelected(false);
				flipBtn.setSelected(false);
				comparisonScreenshotPanel.setComparisonMode(ComparisonMode.differencesZonesDrawn);
			}

			private void diffOnlyButtonSelected() {
				xorBtn.setSelected(false);
				flipBtn.setSelected(false);
				diffDrawnBtn.setSelected(false);
				comparisonScreenshotPanel.setComparisonMode(ComparisonMode.differenceZonesOnly);
			}

			private void xorButtonSelected() {
				diffOnlyBtn.setSelected(false);
				flipBtn.setSelected(false);
				diffDrawnBtn.setSelected(false);
				comparisonScreenshotPanel.setComparisonMode(ComparisonMode.xor);
			}

			private void flipButtonSelected() {
				diffOnlyBtn.setSelected(false);
				xorBtn.setSelected(false);
				diffDrawnBtn.setSelected(false);
				comparisonScreenshotPanel.setComparisonMode(ComparisonMode.flip);
			}
		};

		diffDrawnBtn.addActionListener(toolbarActionListener);
		diffOnlyBtn.addActionListener(toolbarActionListener);
		xorBtn.addActionListener(toolbarActionListener);
		flipBtn.addActionListener(toolbarActionListener);
	}

	private String getCommentFromCSV(String referenceName) {
		return ReferenceComments.get(referenceName);
	}

	private File getReferenceScreenshotFromComparisonXML(File comparisonXML, String rootFolder) {
		StringBuilder builder = new StringBuilder();
		builder.append(rootFolder);
		builder.append("/");
		builder.append(ScreenShooter.REFERENCES_FOLDER_NAME);

		String localTestPath = comparisonXML.getAbsolutePath().replace(rootFolder, "");
		localTestPath = localTestPath.replaceAll("\\\\", "/");
		if (localTestPath.startsWith("/")) {
			localTestPath = localTestPath.replaceFirst("/", "");
		}

		localTestPath = localTestPath.substring(localTestPath.indexOf("/"), localTestPath.length()).replaceAll(".xml", ".png");
		builder.append(localTestPath);

		return new File(builder.toString());
	}

	private void referenceCommentsUpdated() {
		for (ReferenceCommentsListener currentListener : referenceCommentsListeners) {
			currentListener.referenceCommentsUpdated();
		}
	}

	private void showLogFrame() {
		LOGGER.info("displaying log frame...");
		final LogFrame logFrame = new LogFrame();
		logFrame.setVisible(true);
		logFrame.start();
	}
}